﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using Skugo.Shared;
using AvalonDock;
using System.Xml;
using System.Windows;
using System.ComponentModel;
using System.Text.RegularExpressions;

namespace Skugo.Core
{
	// Helper for creating and communicating with dockable plugins
	// The aggrigated dockable member should be marked with the Rpc attribute
	public abstract class DockablePlugin : Plugin
	{
		/// <summary>
		/// The dockable content represents the docked/floating window.
		/// </summary>
        private DockableContent Dock;

        /// <summary>
        /// Gives the user access to the content.
        /// </summary>
        protected Object Content
        {
            get { return this.Dock.Content; }
            set { this.Dock.Content = value; }
        }

        /// <summary>
        /// The name of the dockable plugin.
        /// </summary>
        public String Name { get; private set; }

        private String DockName;

        protected override void Initialize(BinaryReader incoming)
        {
            // Read in the name of the plugin
            this.Name = incoming.ReadAsciiString();

            // We need to force the string to be alpha-numeric
            var regex = new Regex("[^a-zA-Z0-9-]");
            this.DockName = regex.Replace(this.Name, "");

            // Loop through all
            foreach (var dock in this.Client.DockManager.DockableContents)
            {
                // If we found a dock with the same name...
                if (dock.Name == this.DockName)
                {
                    // If the dock already has content, throw an exception (names must be unique!)
                    if (dock.Content != null)
                    {
                        throw new Exception("Window names must be unique. There is already a window with the name of '" + this.Name + "'");
                    }

                    // Set the dock window we'll be using
                    this.Dock = dock;
                    break;
                }
            }

            // If we didn't find a dock window...
            if (this.Dock == null)
            {
                // Create the dockable content window and set our content
                this.Dock = new DockableContent()
                {
                    Name = this.DockName,
                };
            }

            // Set the dock window's title
            this.Dock.Title = this.Name;
            this.Dock.IsCloseable = false;

            // We use the enabled flag upon destruction, so we know
            // not to save the layout when destroying each plugin
            this.Dock.IsEnabled = true;

            // We want to know whenever the state of our window changes
            this.Dock.StateChanged += this.OnStateChanged;

            // Show the form
            this.Dock.Show(this.Client.DockManager);
        }

        // Dispose of this class
        public override void Dispose()
        {
            // If we have a dock content
            if (this.Dock != null)
            {
                // Close the form
                this.Dock.IsCloseable = true;
                this.Dock.IsEnabled = false;
                this.Dock.Close();
                this.Dock = null;
            }
        }

        void OnStateChanged(object sender, RoutedEventArgs e)
        {
            // If the dock is loaded (we aren't just adding it)
            // and it's enabled (we aren't destroying it)
            if (this.Dock.IsLoaded && this.Dock.IsEnabled)
            {
                // Attempt to save the layout
                ProjectClient.AttemptSaveLayout(this.Client);
            }
        }
    }
}
